import { Context } from 'koa';
import { AppContext } from '@/types';
import { OssConfig } from '@/models';
import * as response from '@/utils/response';
import { validate, commonSchemas } from '@/utils/validator';
import logger from '@/utils/logger';
import Joi from 'joi';
import { Op } from 'sequelize';

/**
 * OSS配置控制器
 */
class OssConfigController {
  /**
   * 获取配置列表
   */
  async list(ctx: Context) {
    const appCtx = ctx as AppContext;

    const schema = Joi.object({
      page: commonSchemas.page,
      pageSize: commonSchemas.pageSize,
      name: Joi.string().allow('').optional(),
      type: Joi.string().allow('').optional(),
    });

    const params = await validate<any>(ctx.query as any, schema);

    try {
      // 查询全局配置和当前租户的配置
      const where: any = {
        [Op.or]: [
          { tenantId: { [Op.is]: null } }, // 全局配置
          { tenantId: appCtx.state.user!.tenantId }, // 租户配置
        ],
      };

      if (params.name) {
        where.name = { [Op.like]: `%${params.name}%` };
      }

      if (params.type) {
        where.type = params.type;
      }

      const { rows, count } = await OssConfig.findAndCountAll({
        where,
        limit: params.pageSize,
        offset: (params.page - 1) * params.pageSize,
        order: [['isDefault', 'DESC'], ['createdAt', 'DESC']],
      });

      response.paginated(ctx, rows, count, params.page, params.pageSize);
    } catch (error) {
      logger.error('获取OSS配置列表失败:', error);
      ctx.throw(500, '获取OSS配置列表失败');
    }
  }

  /**
   * 获取单个配置
   */
  async get(ctx: Context) {
    const { id } = ctx.params;

    try {
      const config = await OssConfig.findByPk(id);

      if (!config) {
        return response.error(ctx, '配置不存在', 404);
      }

      response.success(ctx, config);
    } catch (error) {
      logger.error('获取OSS配置失败:', error);
      ctx.throw(500, '获取OSS配置失败');
    }
  }

  /**
   * 创建配置
   */
  async create(ctx: Context) {
    const appCtx = ctx as AppContext;

    const schema = Joi.object({
      name: Joi.string().max(100).required(),
      type: Joi.string().valid('minio', 'oss', 's3', 'local').required(),
      endpoint: Joi.string().max(255).required(),
      port: Joi.number().integer().min(1).max(65535).required(),
      useSsl: Joi.boolean().default(true),
      accessKey: Joi.string().max(255).required(),
      secretKey: Joi.string().max(255).required(),
      bucketName: Joi.string().max(100).required(),
      region: Joi.string().max(100).optional(),
      isDefault: Joi.boolean().default(false),
      isActive: Joi.boolean().default(true),
      maxFileSize: Joi.number().integer().min(1).max(1024).default(50),
      allowedTypes: Joi.string().allow('').optional(),
      remark: Joi.string().max(500).allow('').optional(),
    });

    const data = await validate<any>(ctx.request.body as any, schema);

    try {
      // 如果设置为默认配置，需要取消其他默认配置
      if (data.isDefault) {
        await OssConfig.update(
          { isDefault: false },
          {
            where: {
              [Op.or]: [
                { tenantId: { [Op.is]: null } as any },
                { tenantId: appCtx.state.user!.tenantId },
              ],
            } as any,
          }
        );
      }

      const config = await OssConfig.create({
        ...data,
        tenantId: null, // OSS配置默认为全局配置
      } as any);

      logger.info(`创建OSS配置成功: ${data.name} by ${appCtx.state.user!.email}`);
      response.success(ctx, config, '创建成功');
    } catch (error: any) {
      logger.error('创建OSS配置失败:', error);
      if (error.name === 'SequelizeUniqueConstraintError') {
        ctx.throw(400, '配置名称已存在');
      }
      ctx.throw(500, '创建OSS配置失败');
    }
  }

  /**
   * 更新配置
   */
  async update(ctx: Context) {
    const appCtx = ctx as AppContext;
    const { id } = ctx.params;

    const schema = Joi.object({
      name: Joi.string().max(100).optional(),
      type: Joi.string().valid('minio', 'oss', 's3', 'local').optional(),
      endpoint: Joi.string().max(255).optional(),
      port: Joi.number().integer().min(1).max(65535).optional(),
      useSsl: Joi.boolean().optional(),
      accessKey: Joi.string().max(255).optional(),
      secretKey: Joi.string().max(255).optional(),
      bucketName: Joi.string().max(100).optional(),
      region: Joi.string().max(100).optional(),
      isDefault: Joi.boolean().optional(),
      isActive: Joi.boolean().optional(),
      maxFileSize: Joi.number().integer().min(1).max(1024).optional(),
      allowedTypes: Joi.string().allow('').optional(),
      remark: Joi.string().max(500).allow('').optional(),
    });

    const data = await validate<any>(ctx.request.body as any, schema);

    try {
      const config = await OssConfig.findByPk(id);

      if (!config) {
        return response.error(ctx, '配置不存在', 404);
      }

      // 如果设置为默认配置，需要取消其他默认配置
      if (data.isDefault) {
        await OssConfig.update(
          { isDefault: false },
          {
            where: {
              id: { [Op.ne]: id },
              [Op.or]: [
                { tenantId: { [Op.is]: null } as any },
                { tenantId: appCtx.state.user!.tenantId },
              ],
            } as any,
          }
        );
      }

      await config.update(data);

      logger.info(`更新OSS配置成功: ${config.name} by ${appCtx.state.user!.email}`);
      response.success(ctx, config, '更新成功');
    } catch (error: any) {
      logger.error('更新OSS配置失败:', error);
      if (error.name === 'SequelizeUniqueConstraintError') {
        ctx.throw(400, '配置名称已存在');
      }
      ctx.throw(500, '更新OSS配置失败');
    }
  }

  /**
   * 删除配置
   */
  async delete(ctx: Context) {
    const appCtx = ctx as AppContext;
    const { id } = ctx.params;

    try {
      const config = await OssConfig.findByPk(id);

      if (!config) {
        return response.error(ctx, '配置不存在', 404);
      }

      if (config.isDefault) {
        return response.error(ctx, '默认配置不能删除', 400);
      }

      await config.destroy();

      logger.info(`删除OSS配置成功: ${config.name} by ${appCtx.state.user!.email}`);
      response.success(ctx, null, '删除成功');
    } catch (error) {
      logger.error('删除OSS配置失败:', error);
      ctx.throw(500, '删除OSS配置失败');
    }
  }

  /**
   * 获取默认配置
   */
  async getDefault(ctx: Context) {
    const appCtx = ctx as AppContext;

    try {
      const config = await OssConfig.findOne({
        where: {
          isDefault: true,
          isActive: true,
          [Op.or]: [
            { tenantId: { [Op.is]: null } as any },
            { tenantId: appCtx.state.user!.tenantId },
          ],
        } as any,
      });

      if (!config) {
        return response.error(ctx, '未找到默认配置', 404);
      }

      response.success(ctx, config);
    } catch (error) {
      logger.error('获取默认OSS配置失败:', error);
      ctx.throw(500, '获取默认OSS配置失败');
    }
  }
}

export default new OssConfigController();

